#include <basic_types.h>
#include <mediatypes.h>
#include <osal/osal.h>
#include <api/libc/printf.h>
#include <hld/osd/osddrv.h>
#include <api/libttx/ttx_osd.h>
#include <api/libttx/lib_ttx.h>
#include <hld/hld_dev.h>
#include <hld/dis/vpo.h>

#if 0//defined(TTX_SMOOTH) && (SYS_SDRAM_SIZE == 2) && (TTX_COLOR_NUMBER == 16)
#define TTX_SMOOTH_PATCH    1
#else
#define TTX_SMOOTH_PATCH    0
#endif

#if 0//TTX_SMOOTH_PATCH
#define TTX_HORI_SMOOTH     1
#define TTX_VERT_SMOOTH     1
#define TTX_SOFT_ALPHA      1
#endif


#if 0//TTX_SMOOTH_PATCH
#define TTX_BACK_BASE   8
#define TTX_SMTH_BASE   16
static const UINT8 ttx_pallette[4*256] = 
{
    /*front*/
    0x10, 0x80, 0x80, 0x0f,	//black
    0x50, 0x5b, 0xec, 0x0f,	//red
    0x8f, 0x37, 0x24, 0x0f,	//green
    0xd0, 0x12, 0x90, 0x0f,	//yellow
    0x27, 0xec, 0x6e, 0x0f,	//blue
    0x68, 0xc7, 0xda, 0x0f,	//magenta
    0xa7, 0xa3, 0x12, 0x0f,	//cyan
    0xea, 0x7f, 0x7f, 0x0f,	//white
    /*back*/
    0x10, 0x80, 0x80, 0x0f,	//black   
    0x50, 0x5b, 0xec, 0x0f,	//red
    0x8f, 0x37, 0x24, 0x0f,	//green
    0xd0, 0x12, 0x90, 0x0f,	//yellow
    0x27, 0xec, 0x6e, 0x0f,	//blue
    0x68, 0xc7, 0xda, 0x0f,	//magenta
    0xa7, 0xa3, 0x12, 0x0f,	//cyan
    0xea, 0x7f, 0x7f, 0x0f,	//white
#if !TTX_SOFT_ALPHA
	//black
	0x10, 0x80, 0x80, 0x0f, //black-black
	0x30, 0x6d, 0xb6, 0x0f, //black-red
	0x4f, 0x5b, 0x52, 0x0f, //black-green
	0x70, 0x49, 0x88, 0x0f, //black-yellow
	0x1b, 0xb6, 0x77, 0x0f, //black-blue
	0x3c, 0xa3, 0xad, 0x0f, //black-magenta
	0x5b, 0x91, 0x49, 0x0f, //black-cyan
	0x7d, 0x7f, 0x7f, 0x0f, //black-white
	//red
	0x30, 0x6d, 0xb6, 0x0f, //red-black
	0x50, 0x5b, 0xec, 0x0f, //red-red
	0x6f, 0x49, 0x88, 0x0f, //red-green
	0x90, 0x36, 0xbe, 0x0f, //red-yellow
	0x3b, 0xa3, 0xad, 0x0f, //red-blue
	0x5c, 0x91, 0xe3, 0x0f, //red-magenta
	0x7b, 0x7f, 0x7f, 0x0f, //red-cyan
	0x9d, 0x6d, 0xb5, 0x0f, //red-white
	//green
	0x4f, 0x5b, 0x52, 0x0f, //green-black
	0x6f, 0x49, 0x88, 0x0f, //green-red
	0x8f, 0x37, 0x24, 0x0f, //green-green
	0xaf, 0x24, 0x5a, 0x0f, //green-yellow
	0x5b, 0x91, 0x49, 0x0f, //green-blue
	0x7b, 0x7f, 0x7f, 0x0f, //green-magenta
	0x9b, 0x6d, 0x1b, 0x0f, //green-cyan
	0xbc, 0x5b, 0x51, 0x0f, //green-white
	//yellow
	0x70, 0x49, 0x88, 0x0f, //yellow-black
	0x90, 0x36, 0xbe, 0x0f, //yellow-red
	0xaf, 0x24, 0x5a, 0x0f, //yellow-green
	0xd0, 0x12, 0x90, 0x0f, //yellow-yellow
	0x7b, 0x7f, 0x7f, 0x0f, //yellow-blue
	0x9c, 0x6c, 0xb5, 0x0f, //yellow-magenta
	0xbb, 0x5a, 0x51, 0x0f, //yellow-cyan
	0xdd, 0x48, 0x87, 0x0f, //yellow-white
	//blue
	0x1b, 0xb6, 0x77, 0x0f, //blue-black
	0x3b, 0xa3, 0xad, 0x0f, //blue-red
	0x5b, 0x91, 0x49, 0x0f, //blue-green
	0x7b, 0x7f, 0x7f, 0x0f, //blue-yellow
	0x27, 0xec, 0x6e, 0x0f, //blue-blue
	0x47, 0xd9, 0xa4, 0x0f, //blue-magenta
	0x67, 0xc7, 0x40, 0x0f, //blue-cyan
	0x88, 0xb5, 0x76, 0x0f, //blue-white
	//magenta
	0x3c, 0xa3, 0xad, 0x0f, //magenta-black
	0x5c, 0x91, 0xe3, 0x0f, //magenta-red
	0x7b, 0x7f, 0x7f, 0x0f, //magenta-green
	0x9c, 0x6c, 0xb5, 0x0f, //magenta-yellow
	0x47, 0xd9, 0xa4, 0x0f, //magenta-blue
	0x68, 0xc7, 0xda, 0x0f, //magenta-magenta
	0x87, 0xb5, 0x76, 0x0f, //magenta-cyan
	0xa9, 0xa3, 0xac, 0x0f, //magenta-white
	//cyan
	0x5b, 0x91, 0x49, 0x0f, //cyan-black
	0x7b, 0x7f, 0x7f, 0x0f, //cyan-red
	0x9b, 0x6d, 0x1b, 0x0f, //cyan-green
	0xbb, 0x5a, 0x51, 0x0f, //cyan-yellow
	0x67, 0xc7, 0x40, 0x0f, //cyan-blue
	0x87, 0xb5, 0x76, 0x0f, //cyan-magenta
	0xa7, 0xa3, 0x12, 0x0f, //cyan-cyan
	0xc8, 0x91, 0x48, 0x0f, //cyan-white
	//white
	0x7d, 0x7f, 0x7f, 0x0f, //white-black
	0x9d, 0x6d, 0xb5, 0x0f, //white-red
	0xbc, 0x5b, 0x51, 0x0f, //white-green
	0xdd, 0x48, 0x87, 0x0f, //white-yellow
	0x88, 0xb5, 0x76, 0x0f, //white-blue
	0xa9, 0xa3, 0xac, 0x0f, //white-magenta
	0xc8, 0x91, 0x48, 0x0f, //white-cyan
	0xea, 0x7f, 0x7f, 0x0f, //white-white
#endif
};
#endif

#if 0  //def TTX_SMOOTH
static BOOL m_flag_smooth = TRUE;
void ttx_enable_smooth(BOOL flag)
{
    m_flag_smooth = flag;
}
#endif

#if 0//TTX_SMOOTH_PATCH
//#define __MM_VSCR_START_ADDR    0x80680000
//#define __MM_VSCR_SIZE          (((OSD_TTX_WIDTH)*(OSD_TTX_HEIGHT))/2)
//static UINT8 *m_pScrBuf = (UINT8 *)__MM_VSCR_START_ADDR;
static UINT8 *m_pScrBuf = (UINT8 *)(((UINT32)(__MM_16BIT_OSD_ADDR) & 0x1fffffff) | 0x80000000);
static struct OSDRect m_rcScr = {0, 0, OSD_TTX_WIDTH, OSD_TTX_HEIGHT};
static UINT8 m_fg_color, m_bg_color;
static void vscr_set_screen_color(UINT8 color)
{
    int i;
    for(i=0; i<__MM_16BIT_OSD_LEN; i++)
        m_pScrBuf[i] = (UINT8)color<<4 | color;
}

static void vscr_open_screen()
{
    struct OSDPara tOpenPara;
    struct OSDRect rect = {704, 574, 16, 2};
    UINT32 osd_memory[2] = {__MM_TTX_OSD_ADDR, __MM_TTX_OSD_LEN};

    if(m_flag_smooth)
    {
        tOpenPara.eMode = OSD_256_COLOR;    
        tOpenPara.uGAlphaEnable = IF_GLOBAL_ALPHA;
        tOpenPara.uGAlpha = 0x0F;
    	tOpenPara.uPalletteSel = 0;    	
        OSDDrv_Open((HANDLE)osd_dev, &tOpenPara);
        OSDDrv_IoCtl((HANDLE)osd_dev, OSD_IO_ADJUST_MEMORY, (UINT32)osd_memory);
		
#ifndef HDTV_SUPPORT
    	OSDDrv_SetPallette((HANDLE)osd_dev, (UINT8*)ttx_pallette, 256, OSDDRV_YCBCR);
#endif

    	if(RET_SUCCESS != OSDDrv_CreateRegion((HANDLE)osd_dev, 0, &rect, &tOpenPara))
        	TTX_PRINTF("%s: create region failed\n", __FUNCTION__);
		
#ifdef HDTV_SUPPORT
    	OSDDrv_SetPallette((HANDLE)osd_dev, (UINT8*)ttx_pallette, 256, OSDDRV_YCBCR);
#endif

    	OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_ON);

        vscr_set_screen_color(TTX_B_BLACK);
    }
}

static void vscr_close_screen()
{
    if(m_flag_smooth)
    {
    	OSDDrv_ShowOnOff((HANDLE)osd_dev, OSDDRV_OFF);
        OSDDrv_Close((HANDLE)osd_dev);
    }
}

#ifdef ENABLE_TTX_SUBT
__ATTRIBUTE_RAM_
#endif
static void vscr_write_region(VSCR *pVscr, struct OSDRect *r)
{
    struct OSDRect br, sr, dr;
    INT16 i;
    UINT8 uFactor = 1;
    UINT8 *dst_buf = m_pScrBuf;
    UINT8 *src_buf = pVscr->lpbScr;

    MEMCPY(&br, &m_rcScr, sizeof(br));
    sr.uLeft = r->uLeft - pVscr->vR.uLeft;
    sr.uTop = r->uTop - pVscr->vR.uTop;
    dr.uLeft = r->uLeft - br.uLeft;
    dr.uTop = r->uTop - br.uTop;
    dr.uHeight = sr.uHeight = r->uHeight;
	dr.uWidth = sr.uWidth = r->uWidth;

    UINT32 uSrcBufOffset = (pVscr->vR.uWidth>>uFactor)*(sr.uTop)+((sr.uLeft)>>uFactor);
	UINT32 uDstBufOffset = (br.uWidth>>uFactor)*(dr.uTop)+((dr.uLeft)>>uFactor);

	for(i=0; i<dr.uHeight; i++)
	{
		MEMCPY(dst_buf+uDstBufOffset, src_buf+uSrcBufOffset, (dr.uWidth)>>uFactor);
		uSrcBufOffset += (pVscr->vR.uWidth>>uFactor);
		uDstBufOffset += (br.uWidth>>uFactor);
	}
}

static UINT8 vscr_get_color(UINT8 *pData, INT16 y)
{
    UINT8 color;

    color = pData[y>>1];
    if(!(y&0x01))
        color >>= 4;
    color &= 0x0F;
    return color;
}

static inline UINT8 vscr_smooth_color(UINT8 c0, UINT8 cR)
{
    UINT8 fg = c0, bg = cR;
    if((fg == m_bg_color && bg == m_fg_color) || 
       (fg >= TTX_BACK_BASE && bg <= TTX_BACK_BASE))
    {
        fg = cR;
        bg = c0;
    }
    else if(fg >= TTX_BACK_BASE && bg > TTX_BACK_BASE)
        return fg;

    fg &= 0x07;
    bg &= 0x07;
    return (TTX_SMTH_BASE + (fg<<3) + bg);
}

#define EXTRACT_COLOR(_color)   (((_color)>>4)&0x0F) | (((_color)<<8)&0x0F00) | \
                                (((_color)<<4)&0x0F0000) | (((_color)<<16)&0x0F000000);
#if TTX_HORI_SMOOTH && TTX_VERT_SMOOTH
#ifdef ENABLE_TTX_SUBT
__ATTRIBUTE_RAM_
#endif
static void vscr_smooth_region(VSCR *pVscr, struct OSDRect *r)
{
    struct OSDRect br, sr, dr;
    INT16 i, j, k;
    UINT8 uFactor = 1, uDstFactor = 0;
    UINT8 *dst_buf = pVscr->lpbScr;
    UINT8 *src_buf = m_pScrBuf;
    UINT8 c0;
    UINT16 *ptr_cur, *ptr_nxt;
    UINT32 *ptr_dst;
    UINT32 clr_dst, clr_src, clr_down, clr_right, clr_hmsk, clr_vmsk, clr_tmp;

    MEMCPY(&br, &m_rcScr, sizeof(br));
    r->uLeft -= 2;
    r->uWidth += 2;

    if(r->uLeft & 0x03)
    {
        r->uLeft -= 2;
        r->uWidth += 2;
    }
    if(r->uWidth & 0x03)
        r->uWidth += 2;

    pVscr->vR.uLeft = r->uLeft;
    if(pVscr->vR.uWidth < r->uWidth)
        pVscr->vR.uWidth = r->uWidth;

    if(r->uTop > 0)
    {
        r->uTop--;
        r->uHeight++;
        pVscr->vR.uTop = r->uTop;
        if(pVscr->vR.uHeight < r->uHeight)
            pVscr->vR.uHeight = r->uHeight;
    }

    sr.uLeft = r->uLeft - br.uLeft;
    sr.uTop = r->uTop - br.uTop;
    dr.uLeft = r->uLeft - pVscr->vR.uLeft;
    dr.uTop = r->uTop - pVscr->vR.uTop;
    dr.uHeight = sr.uHeight = r->uHeight;
	dr.uWidth = sr.uWidth = r->uWidth;

	UINT32 uSrcOffset = (br.uWidth>>uFactor)*(sr.uTop)+((sr.uLeft)>>uFactor);
    UINT32 uDstOffset = (pVscr->vR.uWidth>>uDstFactor)*(dr.uTop)+((dr.uLeft)>>uDstFactor);
    UINT32 uNextOffset;
    BOOL fBottom;

	for(i=0; i<dr.uHeight; i++)
	{
        if((sr.uTop + i) < (br.uHeight-1))
        {
            uNextOffset = uSrcOffset + (br.uWidth>>uFactor);
            fBottom = FALSE;
        }
        else
        {
            uNextOffset = uSrcOffset;
            fBottom = TRUE;
        }

//        ASSERT(!(uDstOffset & 0x03));
//        ASSERT(!(uSrcOffset & 0x01));
        ptr_dst = (UINT32 *)&dst_buf[uDstOffset];
        ptr_cur = (UINT16 *)&src_buf[uSrcOffset];
        ptr_nxt = (UINT16 *)&src_buf[uNextOffset];
        clr_tmp = (UINT32)*ptr_cur++;
        clr_tmp = EXTRACT_COLOR(clr_tmp);
        for(j=0; j<dr.uWidth; j+=4)
        {
            clr_src = clr_tmp;
            clr_right = (UINT32)*ptr_cur++;
            clr_right = EXTRACT_COLOR(clr_right);
            clr_tmp = clr_right;
            clr_right = (clr_src >> 8) | (clr_right << 24);
            clr_hmsk = clr_src ^ clr_right;

            clr_down = (UINT32)*ptr_nxt++;
            clr_down = fBottom ? 0x08080808 : EXTRACT_COLOR(clr_down);
            clr_vmsk = clr_src ^ clr_down;

            clr_dst = clr_src;
            for(k=0; clr_vmsk || clr_hmsk; k+=8, clr_vmsk>>=8, clr_hmsk>>=8)
            {
                if(clr_vmsk >= TTX_BACK_BASE) // 0xFF
                    c0 = vscr_smooth_color(clr_src>>k, clr_down>>k);
                else if(clr_hmsk >= TTX_BACK_BASE)  // 0xFF
                    c0 = vscr_smooth_color(clr_src>>k, clr_right>>k);
                else
                    continue;
                clr_dst &= ~((UINT32)0xFF<<k);
                clr_dst |= ((UINT32)c0)<<k;
            }
            *ptr_dst++ = clr_dst;
        }
		uSrcOffset += (br.uWidth>>uFactor);
		uDstOffset += (pVscr->vR.uWidth>>uDstFactor);
	}
}
#elif TTX_VERT_SMOOTH
static void vscr_smooth_region(VSCR *pVscr, struct OSDRect *r)
{
    struct OSDRect br, sr, dr;
    INT16 i, j;
    UINT8 uFactor = 1, uDstFactor = 0;
    UINT8 *dst_buf = pVscr->lpbScr;
    UINT8 *src_buf = m_pScrBuf;
    UINT8 c0, cL, cR, cU, cD, cT;

    MEMCPY(&br, &m_rcScr, sizeof(br));

    if(r->uTop > 0)
    {
        r->uTop--;
        r->uHeight++;
        pVscr->vR.uTop = r->uTop;
        pVscr->vR.uHeight = r->uHeight;
    }

    sr.uLeft = r->uLeft - br.uLeft;
    sr.uTop = r->uTop - br.uTop;
    dr.uLeft = r->uLeft - pVscr->vR.uLeft;
    dr.uTop = r->uTop - pVscr->vR.uTop;
    dr.uHeight = sr.uHeight = r->uHeight;
	dr.uWidth = sr.uWidth = r->uWidth;

	UINT32 uSrcOffset = (br.uWidth>>uFactor)*(sr.uTop)+((sr.uLeft)>>uFactor);
    UINT32 uDstOffset = (pVscr->vR.uWidth>>uDstFactor)*(dr.uTop)+((dr.uLeft)>>uDstFactor);
    UINT32 uNextOffset;

	for(i=0; i<dr.uHeight; i++)
	{
        if((sr.uTop + i) < (br.uHeight-1))
            uNextOffset = uSrcOffset + (br.uWidth>>uFactor);
        else
            uNextOffset = uSrcOffset;
            
        for(j=0; j<dr.uWidth; j++)
        {
            c0 = vscr_get_color(src_buf+uSrcOffset, j);
            cD = vscr_get_color(src_buf+uNextOffset, j);
            if(c0 != cD)
                dst_buf[uDstOffset+j] = vscr_smooth_color(c0, cD);
            else
                dst_buf[uDstOffset+j] = c0;
        }
		uSrcOffset += (br.uWidth>>uFactor);
		uDstOffset += (pVscr->vR.uWidth>>uDstFactor);
	}
}
#elif TTX_HORI_SMOOTH
static void vscr_smooth_region(VSCR *pVscr, struct OSDRect *r)
{
    struct OSDRect br, sr, dr;
    INT16 i, j;
    UINT8 uFactor = 1, uDstFactor = 0;
    UINT8 *dst_buf = pVscr->lpbScr;
    UINT8 *src_buf = m_pScrBuf;
    UINT8 c0, cL, cR, cU, cD, cT;

    MEMCPY(&br, &m_rcScr, sizeof(br));
    r->uLeft -= 2;
//    if(r->uLeft < OSD_TTX_XOFFSET)
//        r->uLeft = OSD_TTX_XOFFSET;
    r->uWidth += 2;
//    if((r->uLeft + r->uWidth) > br.uWidth)
//        r->uWidth = br.uWidth - r->uLeft;
    pVscr->vR.uLeft = r->uLeft;
    if(pVscr->vR.uWidth < r->uWidth)
        pVscr->vR.uWidth = r->uWidth;

    sr.uLeft = r->uLeft - br.uLeft;
    sr.uTop = r->uTop - br.uTop;
    dr.uLeft = r->uLeft - pVscr->vR.uLeft;
    dr.uTop = r->uTop - pVscr->vR.uTop;
    dr.uHeight = sr.uHeight = r->uHeight;
	dr.uWidth = sr.uWidth = r->uWidth;

	UINT32 uSrcOffset = (br.uWidth>>uFactor)*(sr.uTop)+((sr.uLeft)>>uFactor);
    UINT32 uDstOffset = (pVscr->vR.uWidth>>uDstFactor)*(dr.uTop)+((dr.uLeft)>>uDstFactor);

	for(i=0; i<dr.uHeight; i++)
	{
        dst_buf[uDstOffset] = vscr_get_color(src_buf+uSrcOffset, 0);
        cR = vscr_get_color(src_buf+uSrcOffset, 1);
        for(j=1; j<dr.uWidth; j++)
        {
            c0 = cR;
            cR = vscr_get_color(src_buf+uSrcOffset, j+1);
            if(c0 != cR)
                dst_buf[uDstOffset+j] = vscr_smooth_color(c0, cR);
            else
                dst_buf[uDstOffset+j] = c0;
        }
		uSrcOffset += (br.uWidth>>uFactor);
		uDstOffset += (pVscr->vR.uWidth>>uDstFactor);
	}
}
#else
static void vscr_smooth_region(VSCR *pVscr, struct OSDRect *r)
{
    struct OSDRect br, sr, dr;
    INT16 i, j;
    UINT8 uFactor = 1, uDstFactor = 0;
    UINT8 *dst_buf = pVscr->lpbScr;
    UINT8 *src_buf = m_pScrBuf;
    UINT16 *ptr_src;
    UINT32 *ptr_dst;
    UINT32 color;

    MEMCPY(&br, &m_rcScr, sizeof(br));

    if(r->uLeft & 0x03)
    {
        r->uLeft -= 2;
        r->uWidth += 2;
    }
    if(r->uWidth & 0x03)
        r->uWidth += 2;
    pVscr->vR.uLeft = r->uLeft;
    if(pVscr->vR.uWidth < r->uWidth)
        pVscr->vR.uWidth = r->uWidth;
    
    sr.uLeft = r->uLeft - br.uLeft;
    sr.uTop = r->uTop - br.uTop;
    dr.uLeft = r->uLeft - pVscr->vR.uLeft;
    dr.uTop = r->uTop - pVscr->vR.uTop;
    dr.uHeight = sr.uHeight = r->uHeight;
	dr.uWidth = sr.uWidth = r->uWidth;
    ASSERT(!(dr.uWidth&0x01));

	UINT32 uSrcOffset = (br.uWidth>>uFactor)*(sr.uTop)+((sr.uLeft)>>uFactor);
    UINT32 uDstOffset = (pVscr->vR.uWidth>>uDstFactor)*(dr.uTop)+((dr.uLeft)>>uDstFactor);

	for(i=0; i<dr.uHeight; i++)
	{
        ASSERT(!(uDstOffset & 0x03));
        ASSERT(!(uSrcOffset & 0x01));
        ptr_dst = (UINT32 *)&dst_buf[uDstOffset];
        ptr_src = (UINT16 *)&src_buf[uSrcOffset];
        ASSERT(!((UINT32)ptr_dst & 0x03));
        ASSERT(!((UINT32)ptr_src & 0x01));
        for(j=0; j<dr.uWidth; j+=4)
        {
            color = (UINT32)*ptr_src++;
            color = EXTRACT_COLOR(color);
            *ptr_dst++ = color;
        }
		uSrcOffset += (br.uWidth>>uFactor);
		uDstOffset += (pVscr->vR.uWidth>>uDstFactor);
	}
}
#endif

static void vscr_flicker_free(VSCR *pVscr, struct OSDRect *r, UINT8 fg_color, UINT8 bg_color)
{
    if(!m_flag_smooth)
        return;

    m_fg_color = fg_color;
    m_bg_color = bg_color;
//    libc_printf("raw bitmap:\n");
//    dump_bitmap(pVscr->lpbScr, pVscr->vR.uWidth, r->uWidth, r->uHeight, 1);
    vscr_write_region(pVscr, r);
//    MEMSET(pVscr->lpbScr, 0, __MM_TTX_TMP_BUF_LEN);
    vscr_smooth_region(pVscr, r);
//    libc_printf("smooth bitmap:\n");
//    dump_bitmap(pVscr->lpbScr, pVscr->vR.uWidth, r->uWidth, r->uHeight, 0);
}
#endif

extern volatile BOOL ttx_show_on;
extern VSCR TTX_Vscr ;
extern struct osd_device *osd_dev;
extern UINT8 m_bCurRegion;
extern struct ttx_config_par g_ttx_pconfig_par;

extern UINT32 osd_ttx_width;
extern UINT32 osd_ttx_height;
//extern UINT32 osd_ttx_startcol;
//extern UINT32 osd_ttx_startrow;
extern UINT32 osd_ttx_xoffset;
extern UINT32 osd_ttx_yoffset;

extern UINT32* find_char(UINT16 charset, UINT8 character, UINT8 p26_char_set);

const UINT8 ttx_pallette_16[4*16] = {
				/*front*/
				0x10, 0x80, 0x80, 0x0f,	//black
				0x50, 0x5b, 0xec, 0x0f,	//red
				0x8f, 0x37, 0x24, 0x0f,	//green
				0xd0, 0x12, 0x90, 0x0f,	//yellow
				0x27, 0xec, 0x6e, 0x0f,	//blue
				0x68, 0xc7, 0xda, 0x0f,	//magenta
				0xa7, 0xa3, 0x12, 0x0f,	//cyan
				0xea, 0x7f, 0x7f, 0x0f,	//white
				/*back*/
				0x10, 0x80, 0x80, 0x0f,	//black   
				0x50, 0x5b, 0xec, 0x0f,	//red
				0x8f, 0x37, 0x24, 0x0f,	//green
				0xd0, 0x12, 0x90, 0x0f,	//yellow
				0x27, 0xec, 0x6e, 0x0f,	//blue
				0x68, 0xc7, 0xda, 0x0f,	//magenta
				0xa7, 0xa3, 0x12, 0x0f,	//cyan
				0xea, 0x7f, 0x7f, 0x0f,	//white
};

void TTX_DrawChar_16(UINT16 x, UINT16 y, UINT16 charset, UINT8 fg_color, UINT8 bg_color,UINT8 double_width,UINT8 double_height, UINT8 character, UINT8 p26_char_set)
{
	UINT8* pData; 
	struct OSDRect r;
      INT16 dw,dh;
	UINT8 charset_idx, char_idx;
	UINT32 charmask;
	UINT16 bit_count;
	UINT8 i, j, k;
	UINT8 data1, data2;
	UINT8 zoomkind;
	UINT8 temp;
	UINT32*  char_addr;

	if(ttx_show_on!=TRUE)
		return;

	//if(character < 0x20 ||character > 0x7f)
	//	return;
	if((x%TTX_CHAR_W) != 0 || (y%TTX_CHAR_H) != 0 || x+TTX_CHAR_W > osd_ttx_width)
	{
		//libc_printf("-----------------TTX_DrawChar(), parameter illegal,x=%d,y=%d\n",x,y);
		return ;
	}

    if(get_ttxmenu_status()== TRUE && get_ttxinfo_status() == TRUE)
    {
        if(y+TTX_CHAR_H > osd_ttx_height+TTX_CHAR_H)
            return;
    }
    else
    {
        if(y+TTX_CHAR_H > osd_ttx_height)
            return;
    }

	if(double_width && (x>=39*TTX_CHAR_W))
		double_width = 0;
	if(double_height && (y>=24*TTX_CHAR_H))
		double_height = 0;
	
	 if(double_width)  
	 	{
			
			//PRINTF("---------TTX_DrawChar(), OSD_STRIDE = %d \n", OSD_STRIDE);
			dw = 28;
			if(double_height) //vertical zoom double
				{
					dh = 40;
					zoomkind = 4;
				}
			else		// vertical normal
				{
					dh = 20;
					zoomkind = 3;
				}
	 	}
	 else	//horizion normal	
	 	{
			
			//PRINTF("---------TTX_DrawChar(), OSD_STRIDE = %d \n", OSD_STRIDE);
			dw = 14;
			if(double_height)	//vertical zoom  double
				{
					dh = 40;
					zoomkind = 2;
				}
			else		//vertical normal
				{
					dh = 20;
					zoomkind = 1;
				}
	 	}
	//TTX_PRINTF("---------TTX_DrawChar(), -----2, double_width=%d, double_height=%d\n",double_width, double_height);
		
	//set TTX_Vscr size
	
	r.uLeft = x + osd_ttx_xoffset;
	r.uTop = y + osd_ttx_yoffset;
	r.uWidth = dw;
	r.uHeight = dh;
		
	TTX_Vscr.vR.uLeft = r.uLeft;
	TTX_Vscr.vR.uTop = r.uTop;
	TTX_Vscr.vR.uWidth = TTX_CHAR_W*2;
	TTX_Vscr.vR.uHeight = TTX_CHAR_H*2;
	
	TTX_Vscr.lpbScr = g_ttx_pconfig_par.ttx_vscrbuf;
	pData = TTX_Vscr.lpbScr;
			

	bit_count = 0;
	char_addr = find_char( charset, character, p26_char_set);
	if(char_addr == NULL) return;

				switch(zoomkind)
				{
				     case 1:			//vertical normal , horizine normal
				     	for(i = 0 ;i < 9;i++)
				     	{
				     		charmask = 0x80000000;	
						for(j = 0 ;j < 16 ;j++)
		   				{
						if(bit_count >= TTX_CHAR_W * TTX_CHAR_H)	//char draw finished
							break;
					
						if(bit_count!=0 && bit_count %14 ==0)	//one row finished, change to next
							pData += 7;
						//TTX_PRINTF("------------------charmask = %x \n",charmask);
						//16 color, 2 pixels per byte 
						//if(TTX_Font[charset_idx][char_idx][i] & charmask)
						if(*char_addr & charmask)
							data1 = fg_color;
						else
							data1 = bg_color;
						
						charmask = charmask>>1;
						//TTX_PRINTF("------------------charmask = %x \n",charmask);
						//if(TTX_Font[charset_idx][char_idx][i] & charmask)
						if(*char_addr & charmask)
							data2 = fg_color;
						else
							data2 = bg_color;
						
						*pData = (data2 & 0x0f) | ((data1 & 0x0f)<<4);
						//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----normal, pData = %d, *pData = %x\n",  pData, *pData);
						pData++;
						bit_count += 2;
						charmask = charmask>>1;
															
		   				}
						char_addr += 1;
						//TTX_PRINTF("-----TTX_DrawChar(),-----4,   -----normal,  %d  UINT32 = %x draw finished!\n", i, TTX_Font[charset_idx][char_idx][i]);
				     	}
						break;
					case 2:			//vertical zoom  double, horizine normal
					 for(i = 0 ;i < 9;i++)
				     	 {
				     		charmask = 0x80000000;	
					      for(j = 0;j < 16;j++)
						{	
							if(bit_count >= TTX_CHAR_W * TTX_CHAR_H)
								break;
							if(bit_count!=0 && bit_count %14 ==0)
       							pData += 7*3;
       						//if(TTX_Font[charset_idx][char_idx][i] & charmask)
       						if(*char_addr & charmask)
								data1 = fg_color;
							else
								data1 = bg_color;
							charmask = charmask>>1;
							//if(TTX_Font[charset_idx][char_idx][i] & charmask)
							if(*char_addr & charmask)
								data2 = fg_color;
							else
								data2 = bg_color;
							*pData = (data2 & 0x0f) | ((data1 & 0x0f)<<4);
							//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double uHeight, pData = %d, *pData = %x\n",  pData, *pData);
							*(pData + 14) = *pData;
							//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double uHeight, pData+14 = %d, *(pData+14) = %x\n",  pData+14, *(pData + 14));
       						pData++;
       						bit_count += 2;
       						charmask = charmask>>1;
						}
						//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double uHeight,  %d UINT32 = %x draw finished!\n", i, TTX_Font[charset_idx][char_idx][i]);
						char_addr += 1;
					 }
						break;
					case 3:		 //horizine zoom  double, vertical normal
					   for(i = 0 ;i < 9;i++)
				     	  {
				     		charmask = 0x80000000;
					      for(j=0;j<16;j++)
						{
							if(bit_count >= TTX_CHAR_W * TTX_CHAR_H)
								break;
							//if(TTX_Font[charset_idx][char_idx][i] & charmask)
							if(*char_addr & charmask)
								data1 = fg_color;
							else
								data1 = bg_color;
						
							charmask = charmask>>1;
						
							//if(TTX_Font[charset_idx][char_idx][i] & charmask)
							if(*char_addr & charmask)
								data2 = fg_color;
							else
								data2 = bg_color;

							*pData = (data2 & 0x0f) | ((data1 & 0x0f)<<4);
							temp = *pData; 
             					pData++;
							*pData = temp;
							
							pData++;
							bit_count += 2;
             					charmask = charmask>>1;
						}
						//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double uWidth,  %d UINT32 = %x draw finished!\n", i, TTX_Font[charset_idx][char_idx][i]);
						char_addr += 1;
					   }
						break;
					 case 4:			 //horizine zoom  double, vertical double
						for(i = 0 ;i < 9;i++)
				     		{
				     			charmask = 0x80000000;
							for(j = 0;j < 16;j++)
             						{
									if(bit_count == TTX_CHAR_W * TTX_CHAR_H)
										break;
									if(bit_count!=0 && bit_count % 14 ==0)
										pData += 7*2;
									//if(TTX_Font[charset_idx][char_idx][i] & charmask)
									if(*char_addr & charmask)
										data1 = fg_color;
									else
										data1 = bg_color;
						
									charmask = charmask>>1;
						
									//if(TTX_Font[charset_idx][char_idx][i] & charmask)
									if(*char_addr & charmask)
										data2 = fg_color;
									else
										data2 = bg_color;

									*pData = (data2 & 0x0f) | ((data1 & 0x0f)<<4);
									temp = *pData; 
									*(pData + 14) = temp;
									*(pData + 15) = temp;
             							pData++;
									*pData = temp;
									//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double both, *pData = %x\n", *pData);
                          					pData++;
                          					charmask = charmask>>1;
									bit_count += 2;
             						}
             						//TTX_PRINTF("-----TTX_DrawChar(),-----4,-----double both,  %d UINT32 = %x  draw finished!\n", i, TTX_Font[charset_idx][char_idx][i]);
								char_addr += 1;
						}
							break;

					default:
							break;
				}

	// write Vscr data to osd frame buffer
#if 0//TTX_SMOOTH_PATCH
    vscr_flicker_free(&TTX_Vscr, &r, fg_color, bg_color);
#endif
	OSDDrv_RegionWrite((HANDLE)osd_dev, m_bCurRegion, &TTX_Vscr, &r);

}

